package org.jimmy.tang.concurrent.locks;

/**
 * @author jimmy
 * 
 */
public class LeftRightDeadLock {
    final Object left = new Object();
    final Object right = new Object();

    public void doLeftRight() {
        synchronized (left) {
            synchronized (right) {
                execute1();
            }
        }
    }

    public void doRightLeft() {
        synchronized (right) {
            synchronized (left) {
                execute2();
            }
        }
    }

    private void execute2() {
    }

    private void execute1() {
    }

    /**
     * dead lock
     * @param fromAccount
     * @param toAccount
     * @param amount
     */
    public void transferMoney(Account fromAccount,//
            Account toAccount,//
            int amount) {
        synchronized (fromAccount) {
            synchronized (toAccount) {
                fromAccount.decr(amount);
                toAccount.add(amount);
            }
        }
    }

    Object lock = new Object();

    /**
     * no dead lock
     * @param fromAccount
     * @param toAccount
     * @param amount
     */
    public void transferMoney1(Account fromAccount,//
            Account toAccount,//
            int amount) {
        int order = fromAccount.name().compareTo(toAccount.name());
        Object lockFirst = order > 0 ? toAccount : fromAccount;
        Object lockSecond = order > 0 ? fromAccount : toAccount;
        if (order == 0) {
            synchronized (lock) {
                synchronized (lockFirst) {
                    synchronized (lockSecond) {
                        // do work
                    }
                }
            }

        } else {
            synchronized (lockFirst) {
                synchronized (lockSecond) {
                    // do work
                }
            }
        }
    }

    class Account {
        void decr(int num) {
        }

        void add(int num) {
        }

        String name() {
            return "";
        };

    }
}
